R Notebook Questions, refined:

Do more Marylanders donate to in-state or out-of-state candidates? Which out-of-state candidates received the most donations and the greatest amount of money in donations? What are the demographics of people who donate to Maryland races only? To out-of-state races only? (using voter data OR using census data to see if those donors are clustered in specific locations, and, if they are, what the makeups of those locations are) Among top Maryland donors, what professions donate the most money to senate campaigns? What’s the makeup of donations received by Hogan and Alsobrooks? What percentage of their overall donations were large amounts of money (to be defined, but > $1000, for example) vs small amounts? Which party tends to donate more to out-of-state races?

We refined our dataset further by deciding to focus on individual donations made to senate races by donors in Maryland. Using the FEC website, we downloaded a dataset that met those parameters. We cleaned the data by removing unnecessary columns and renaming the columns where needed. We decided to limit our dataset to donations made in 2024 to ensure that the donations were made after the primary and before the general election. We hoped this would limit the number of candidates receiving donations, since most donations will go toward one of two parties in a certain race.

We also cleaned the data-set, removing numerous columns that were N/A or that were unnecessary to our project. We also had to rename one column and then filter to only the report year of 2024 to limit the donations. To answer our first question and questions, we’ll need to separate the out-of-state candidates from in-state candidates, but this should be easy because we’ll just need to filter out the Hogan and Alsobrooks committees to isolate the out-of-state candidates receiving donations. To answer our third question, we’ll need to either call in demographic data from the census or identify specific locations with clusters of donations, and look up information about those locations using census.gov. Question #4 asks about the professions of donors. One obvious challenge here is that professions and titles are often spelled or worded differently, even if they describe the same job– in this dataset, there are 2,738 different professions listed. To try to combat this, we will use open refine to reduce the number of occupations with slight variations in spelling or wording. We will then limit the data set to the top 1000 donations to make the analysis more manageable. We can also make some broad observations about the data even without cleaning the professions– for example, it’s obvious that the most donations come from people who say they are “not employed” (45568) or “retired” (29424). The next highest number of donations is more than 20,000 donations less than the number of donations from retired people. There are 207 committees that received donations in our dataset. Originally, we thought that we would use open refine to sort the committees by candidate name, because we thought that most candidates would have multiple committees. However, we found that this was actually pretty uncommon, and we weren’t able to match any names using open refine, once we uploaded our csv. For question 5, we need to do some extra research to decide how to define large donations. One idea is to find the average or median donation, and use that number as the dividing line between small and large donations. Another idea is to see if there’s an agreed-upon definition by people who work on campaigns or political scientists. We have one extra question (#6) that we would like to answer, but it involves party-level analysis that we can’t do because we don’t have the political parties of the donors in this data, and we don’t have anything in this data that indicates the party of each candidate. To answer this question, we could join this data with data from Act Blue and Win Red to identify the parties of donors. We can also probably find a dataset with the committee names and parties for all senate candidates, and join that dataset with ours.

Turn off scientific notation


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxub3B0aW9ucyhzY2lwZW49OTk5KVxubGlicmFyeSh0aWR5dmVyc2UpXG5saWJyYXJ5KGx1YnJpZGF0ZSlcblxuXG5gYGAifQ== -->

```r
options(scipen=999)
library(tidyverse)
library(lubridate)

```

<!-- rnb-source-end -->
```r
options(scipen=999)
library(tidyverse)
library(lubridate)

<!-- rnb-source-end -->


<!-- rnb-output-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-output-begin eyJkYXRhIjoiXG48IS0tIHJuYi1zb3VyY2UtYmVnaW4gZXlKa1lYUmhJam9pWUdCZ2NseHVhVzV6ZEdGc2JDNXdZV05yWVdkbGN5Z25kR2xrZVdObGJuTjFjeWNwWEc1Z1lHQWlmUT09IC0tPlxuXG5gYGByXG5pbnN0YWxsLnBhY2thZ2VzKCd0aWR5Y2Vuc3VzJylcbmBgYFxuXG48IS0tIHJuYi1zb3VyY2UtZW5kIC0tPlxuIn0= -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuaW5zdGFsbC5wYWNrYWdlcygndGlkeWNlbnN1cycpXG5gYGAifQ== -->

```r
install.packages('tidycensus')

  There is a binary version available but the source version is later:
installing the source package ‘tidycensus’

trying URL 'https://cran.rstudio.com/src/contrib/tidycensus_1.6.7.tar.gz'
Content type 'application/x-gzip' length 2262396 bytes (2.2 MB)
==================================================
downloaded 2.2 MB

* installing *source* package ‘tidycensus’ ...
** package ‘tidycensus’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB

* removing ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
Warning in install.packages :
  installation of package ‘tidycensus’ had non-zero exit status

The downloaded source packages are in
    ‘/private/var/folders/2l/xcvc2w597t9714c985cwdbr40000gp/T/RtmpfQuLsL/downloaded_packages’
library(tidycensus)
md_senate_contributions <- read_csv("data/md_senate_contributions.csv") |>


print(column_names)
New names:Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
  dat <- vroom(...)
  problems(dat)Rows: 115275 Columns: 79── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (44): committee_id, committee_name...2, report_type, line_number, transaction_id, entity_type, entity_type_desc, unused_contbr_id, ...
dbl  (11): report_year, image_number, file_number, contributor_zip, contribution_receipt_amount, contributor_aggregate_ytd, conduit_comm...
lgl  (22): committee_name...9, recipient_committee_org_type, memo_code_full, candidate_id, candidate_name, candidate_first_name, candida...
dttm  (2): contribution_receipt_date, load_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

#clean data

cleaned_data <- md_senate_contributions |>

select( -unused_contbr_id, -committee_name...9, -recipient_committee_org_type, -contributor_suffix, -contributor_street_2, -contributor_id, -memo_code, -memo_code_full, -candidate_id, -candidate_name, -candidate_first_name, -candidate_last_name, -candidate_middle_name, -candidate_prefix, -candidate_suffix, -candidate_office, -candidate_office_full, -candidate_office_state, -candidate_office_state_full, -candidate_office_district, -conduit_committee_id, -conduit_committee_name, -conduit_committee_street1, -conduit_committee_street2, -conduit_committee_city, -conduit_committee_state, -conduit_committee_zip, -donor_committee_name, -national_committee_nonfederal_account, -election_type_full, -increased_limit, -is_individual) |>

rename(committee_name = `committee_name...2`) |>

filter(report_year == 2024)


colnames(cleaned_data)
 [1] "committee_id"                    "committee_name"                  "report_year"                     "report_type"                    
 [5] "image_number"                    "line_number"                     "transaction_id"                  "file_number"                    
 [9] "entity_type"                     "entity_type_desc"                "contributor_prefix"              "contributor_name"               
[13] "recipient_committee_type"        "recipient_committee_designation" "contributor_first_name"          "contributor_middle_name"        
[17] "contributor_last_name"           "contributor_street_1"            "contributor_city"                "contributor_state"              
[21] "contributor_zip"                 "contributor_employer"            "contributor_occupation"          "receipt_type"                   
[25] "receipt_type_desc"               "receipt_type_full"               "contribution_receipt_date"       "contribution_receipt_amount"    
[29] "contributor_aggregate_ytd"       "election_type"                   "fec_election_type_desc"          "fec_election_year"              
[33] "amendment_indicator"             "amendment_indicator_desc"        "schedule_type_full"              "load_date"                      
[37] "original_sub_id"                 "back_reference_transaction_id"   "back_reference_schedule_name"    "filing_form"                    
[41] "link_id"                         "memo_text"                       "two_year_transaction_period"     "schedule_type"                  
[45] "sub_id"                          "pdf_url"                         "line_number_label"              
most_contributions <- cleaned_data |>
select(committee_name, contribution_receipt_amount) |>
group_by(committee_name) |>
summarize(total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)) |>
arrange(desc(total_contribution)) 
cleaned_data |>
  
write_csv("data/cleaned_md_senate_contributions.csv")
data <- read_delim("data/ccl.txt", delim = "|", col_names = FALSE)
Rows: 8568 Columns: 7── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr (4): X1, X4, X5, X6
dbl (3): X2, X3, X7
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
cleaned_data_ccl <- data |>
rename(candidate_id = X1,candidate_election_year = X2, fec_election_year = X3, committee_id = X4,committee_type = X5,committee_design = X6, linkage_id = X7)

#inner join the committee id and fec election year

joined_data <- inner_join(cleaned_data, cleaned_data_ccl, by = c("committee_id", "fec_election_year"))
Warning: Detected an unexpected many-to-many relationship between `x` and `y`.

#insert the candidate data

candidate_data <- read_delim("data/candidate_data.txt", delim = "|", col_names = FALSE) |>
  select(X1, X2, X3, X5) |> 
 rename(candidate_id = X1, candidate_name = X2, candidate_party = X5)
Rows: 3824 Columns: 30── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr  (7): X1, X2, X3, X5, X19, X20, X28
dbl (18): X4, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X26, X27, X29, X30
lgl  (5): X21, X22, X23, X24, X25
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
candidate_joined_data <- inner_join(joined_data, candidate_data, by =c("candidate_id"))

#include only these rows


final_data <- candidate_joined_data |>
select(committee_id, committee_name, report_year, entity_type_desc,contributor_prefix, contributor_name, contributor_first_name, contributor_last_name, contributor_middle_name, contributor_street_1,contributor_city, contributor_state, contributor_zip,contributor_employer, contributor_occupation, contribution_receipt_date, contribution_receipt_amount, contributor_aggregate_ytd,memo_text,pdf_url, candidate_id, candidate_election_year)

Q1: Do more Marylanders donate to in-state or out-of-state candidates?

final_data_states <- final_data |>
  mutate(state = substr(candidate_id, 3, 4))
state_contributions <- final_data_states |>
  group_by(state) |>
  summarise(
    contribution_count = n(),                
    total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)  
  )
maryland_contrib <- state_contributions |>
  filter(state == "MD") |>
  summarise(total_maryland_contrib = sum(total_contribution, na.rm = TRUE))


other_states_contrib <- state_contributions |>
  filter(state != "MD") |>
  summarise(total_other_states_contrib = sum(total_contribution, na.rm = TRUE))


comparison <- data.frame(
  state = c("Maryland", "Other States"),
  total_contribution = c(maryland_contrib$total_maryland_contrib, other_states_contrib$total_other_states_contrib)
)

A: Montana was surprisingly the state with the most contributions — edging Maryland with 202 more contributions Maryland. Maryland received the highest total sum however, with $5,516,562.24. That was $4,074,226.07 more than the next highest state, which was Montana. The other states combined recieved $7,358,970, a little less than two million more than just the state of Maryland.

Q2: Which out-of-state candidates received the most donations and the greatest amount of money in donations?

final_data_no_md <- final_data_states |>
  filter(state != "MD")
contributions_summary <- final_data_no_md |>
  group_by(committee_name) |>
  summarise(
    num_contributions = n(), 
    total_contribution_sum = sum(contribution_receipt_amount, na.rm = TRUE) 
  ) |>
  arrange(committee_name)

A2: Jon Tester, Sherrod Brown and Ruben Gallego were the top three in that order for both contributions recieved and the sum of contributions. The similarity between the three of them is that they were all Democrats running in tightly contested races. Brown was the only to lose his race. Jon Tester also clearly recieved more than the other two — which explains why Montana received so many more out-of-state contributions than other states. Montanans for Tester received 3,679 more contributions and $238,017.96 more in total contributions compared to Friends of Sherrod Brown.

Q3: What are the demographics of people who donate to Maryland races only? To out-of-state races only?

Step 1: find people who donate to ONLY Maryland races.


maryland_only_donors <- final_data_states|>
  group_by(contributor_name) |>                
  summarize(only_md = all(state == "MD")) |>
  filter(only_md) |>                          
  select(contributor_name)                    

full_maryland_only_donors <- final_data_states |>
   filter(contributor_name %in% maryland_only_donors$contributor_name)


zips_full_maryland_only_donors <- full_maryland_only_donors |>
  group_by(contributor_name, contributor_zip) |>
  summarize(
    num_donations = n(),             
    total_donated = sum(contribution_receipt_amount) 
  )|>
  arrange(desc(num_donations))  
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
md_zip_summary <- zips_full_maryland_only_donors |>
  group_by(contributor_zip) |>              
  summarize(
    num_donations = n(),                      
    total_donated = sum(total_donated)      
  ) |>
  arrange(desc(num_donations)) 
all_zcta <- get_acs(
  geography = "zcta",
  variables = c(
 "B01003_001", 
     "B01002_001", #= "median_age",
 "B19013_001", # = "median_income",
  "B02001_002", # = "white_alone",
     "B02001_003", # = "black_alone",
"B02001_004", # = "native_american",
    "B02001_005", #= "asian_alone",
 "B02001_006", # = "hawaiian_pacific",
"B02001_007",  # = "other_race",
    "B02001_008", # = "two_or_more_races"
"B03002_012E"),
  
  year = 2022,
  survey = "acs5",
  output = "wide"
)
Getting data from the 2018-2022 5-year ACS
all_zcta <- all_zcta %>%
  rename(
    total_population = B01003_001E,      
    median_age = B01002_001E,            
    median_income = B19013_001E,        
    white_alone = B02001_002E,          
    black_alone = B02001_003E,         
    native_american = B02001_004E,      
    asian_alone = B02001_005E,          
    hawaiian_pacific = B02001_006E,     
    other_race = B02001_007E,           
    two_or_more_races = B02001_008E,
    hispanic_or_latino = B03002_012E
  )

zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
  mutate(
    contributor_zip = substr(contributor_zip, 1, 5),
    contributor_zip = sprintf("%05s", contributor_zip)
  )

zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
  mutate(contributor_zip = as.character(contributor_zip))

merged_data_md <- zips_full_maryland_only_donors %>%
  left_join(all_zcta, by = c("contributor_zip" = "GEOID"))

summarized_md_donor_demos_by_zip <- merged_data_md %>%
  group_by(contributor_zip) |>
  summarize(
    total_population = first(total_population),  
    median_age = first(median_age),             
    median_income = first(median_income),       
    white_alone = first(white_alone),            
    black_alone = first(black_alone),           
    native_american = first(native_american),   
    asian_alone = first(asian_alone),           
    hawaiian_pacific = first(hawaiian_pacific),  
    other_race = first(other_race),  
     hispanic_or_latino = first(hispanic_or_latino),
    two_or_more_races = first(two_or_more_races),
    num_donations = n(),                      
    total_amt_donated = sum(total_donated, na.rm = TRUE) 
  ) |> 
  arrange(desc(num_donations))  |> 
  mutate(
    white_alone_per_capita = white_alone / total_population,
    black_alone_per_capita = black_alone / total_population,
    native_american_per_capita = native_american / total_population,
    asian_alone_per_capita = asian_alone / total_population,
    hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
    other_race_per_capita = other_race / total_population,
     hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
    two_or_more_races_per_capita = two_or_more_races / total_population,
    median_income_per_capita = median_income / total_population
  ) |>
   mutate(
    white_alone_percent = white_alone_per_capita * 100,
    black_alone_percent = black_alone_per_capita * 100,
    native_american_percent = native_american_per_capita * 100,
    asian_alone_percent = asian_alone_per_capita * 100,
    hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
    other_race_percent = other_race_per_capita * 100,
    hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
    two_or_more_races_percent = two_or_more_races_per_capita * 100,
    median_income_per_capita = median_income_per_capita * 100
  ) |>
 mutate(
    amt_donated_per_resident = total_amt_donated / total_population
  ) |>   
  select(where(~ !all(is.na(.))))

cleaner_md_donor_demos <- summarized_md_donor_demos_by_zip |> 
    select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone") 
 

#repeat for out of state donors

out_of_state_donors <- final_data_states |>
  filter(state != "MD")

xmaryland_donors <- final_data_states |>
  filter(state == "MD")

out_of_state_only_donors <- out_of_state_donors |>
  filter(!contributor_name %in% xmaryland_donors$contributor_name)  |>
group_by(contributor_name, contributor_zip) |>
  summarize(
    num_donations = n(),            
    total_donated = sum(contribution_receipt_amount)  
  ) |>
  arrange(desc(num_donations))  
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
out_of_state_only_donors <- out_of_state_only_donors |>
  mutate(
    contributor_zip = substr(contributor_zip, 1, 5),
    contributor_zip = sprintf("%05s", contributor_zip)
  )

merged_data_oos <- out_of_state_only_donors|>
  left_join(all_zcta, by = c("contributor_zip" = "GEOID"))

cleaner_oos_donor_demos <- merged_data_oos  |>
   group_by(contributor_zip) |>
  summarize(
    total_population = first(total_population), 
    median_age = first(median_age),              
    median_income = first(median_income),        
    white_alone = first(white_alone),         
    black_alone = first(black_alone),            
    native_american = first(native_american),   
    asian_alone = first(asian_alone),           
    hawaiian_pacific = first(hawaiian_pacific),
    other_race = first(other_race),     
    hispanic_or_latino = first(hispanic_or_latino),
    two_or_more_races = first(two_or_more_races),
    num_donations = n(),                      
    total_amt_donated = sum(total_donated, na.rm = TRUE) 
  ) |> 
  arrange(desc(num_donations))  |> 
  mutate(
   
    white_alone_per_capita = white_alone / total_population,
    black_alone_per_capita = black_alone / total_population,
    native_american_per_capita = native_american / total_population,
    asian_alone_per_capita = asian_alone / total_population,
    hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
    other_race_per_capita = other_race / total_population,
    hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
    two_or_more_races_per_capita = two_or_more_races / total_population,
    median_income_per_capita = median_income / total_population
  ) |>
   mutate(
  
    white_alone_percent = white_alone_per_capita * 100,
    black_alone_percent = black_alone_per_capita * 100,
    native_american_percent = native_american_per_capita * 100,
    asian_alone_percent = asian_alone_per_capita * 100,
    hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
    other_race_percent = other_race_per_capita * 100,
    hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
    two_or_more_races_percent = two_or_more_races_per_capita * 100,
    median_income_per_capita = median_income_per_capita * 100  
  ) 

cleaner_oos_donor_demos <- cleaner_oos_donor_demos |> select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone") |> 
  
  mutate(
    amt_donated_per_resident = total_amt_donated / total_population
  ) |>
  select(where(~ !all(is.na(.))))
head(merged_data_oos)
cleaner_oos_donor_demos |>   
  mutate(
    contributor_zip = as.character(contributor_zip),         # Ensure ZIP codes are strings
    contributor_zip = str_pad(contributor_zip, width = 5,    # Pad with leading zeros to ensure 5 digits
                              side = "left", pad = "0"),
    contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"),  # Keep only valid 5-digit ZIP codes
                             contributor_zip, NA))


cleaner_oos_donor_demos |> arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_oos_donor_demos.csv")
cleaner_md_donor_demos |> 
  mutate(
    contributor_zip = as.character(contributor_zip),         # Ensure ZIP codes are strings
    contributor_zip = str_pad(contributor_zip, width = 5,    # Pad with leading zeros to ensure 5 digits
                              side = "left", pad = "0"),
    contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"),  # Keep only valid 5-digit ZIP codes
                             contributor_zip, NA)) |> 
  arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_md_donor_demos.csv")

cleaner_oos_donor_demos |> write_csv(“cleaner_oos_donor_demos.csv”)

It looks like in this data, the top contributing zip codes are the same for out-of-state and in-state donations. The top out-of-state donors donated much more than the in-state donors, and there were more of them in the top zip codes. A top in-state donor zip code is Anapolis, and doesn’t appear in the top ten zip codes for out-of-state.

As we keep going to answer this question, we should calculate the amount donated per person. We should consider presenting this data with two maps side-by-side.

Question 4: Among top Maryland donors, what professions donate the most money to senate campaigns?

individual_donors  <- final_data_states|>
group_by(contributor_name, contributor_zip, contributor_occupation, contributor_employer) |> 
  summarize(
    num_donations = n(),               
    total_donated = sum(contribution_receipt_amount) 
  ) |>
  arrange(desc(num_donations))  

jobs_to_clean <- individual_donors |> 
  group_by(contributor_occupation) |>
  summarize(
    number_jobs = n(),
    num_donations = n(),  
     total_donations = sum(total_donated)
  ) |> arrange(desc(number_jobs)) |>
write_csv("jobs_to_clean.csv")
boss_to_clean  <- individual_donors |> 
  group_by(contributor_employer) |>
  summarize(
    number_jobs = n(),
    num_donations = n(),  
     total_donations = sum(total_donated)
  ) |> arrange(desc(number_jobs)) |>
write_csv("boss_to_clean.csv")
clean_employer <- read_csv("cleaned_boss.csv")
clean_occupation <- read_csv("clean_jobs.csv")

clean_occupation |> 
  group_by(cleaned_jjobs)  |> 
  summarize(
    number_jobs = n(),
    num_donations = n(),  
     total_donated = sum(total_donations)) |> 
  arrange(desc(number_jobs))
clean_occupation |> 
  group_by(cleaned_jjobs)  |> 
  summarize(
    number_jobs = n(),
    num_donations = n(),  
     total_donated = sum(total_donations)) |> 
  arrange(desc(total_donated))
clean_employer |> 
  group_by(cleaned_boss) |>
  summarize(
    number_jobs = n(),
    num_donations = n(),  
     total_donated = sum(total_donations)
  ) |>
  arrange(desc(number_jobs))

To answer this question, I put a csv of occupations into OpenRefine. We originally planned to limit the data set, but I found that there were only 1,963 job titles in the data set, which seemed like a reasonable number to refine down into a smaller list of jobs.

To do this, I grouped certain jobs into categories like “director” and “executive” – so job titles like “sales director” went into the “director” category.

I think the OpenRefine method may be flawed/not tell us very much because I was only able to get the list down to 1,464 jobs after about 1 hour of refining. I also worry that the categorizing method I used obsures information that might be important – Director of Sales is different from Director of Education, for example, and these jobs were grouped into the same position. And there are such variations in job title that I was not able to categorize all job titles well.

What we can tell from this data is that the most frequently-held jobs among Maryland donors are leadership/management positions, so likely well-paid. The most money was donated by people who are not employed or retired.

We should consider repeating this question with information about employers. I’ve started to do this in OpenRefine, but this will take longer, because there are more than 7,000 different employers. However, many of these seem to be able to be reconciled in OpenRefine. And I’m interested to see how many donations/how much money was donated by people who work for top employers in Maryland, like Johns Hopkins.

#Question 5: What’s the makeup of donations received by Hogan and Alsobrooks? What percentage of their overall donations were large amounts of money (to be defined, but > $1000, for example) vs small amounts?

hogan_filtered_data <- final_data |>
  filter(committee_name %in% c("HOGAN FOR MARYLAND INC."))
large_donation_threshold <- 1000

hogan_filtered_data |> mutate( donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small") )

hogan_category_totals <- hogan_filtered_data |>
  mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
  group_by(donation_category) |>
  summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")

hogan_category_totals %>% mutate( percentage = total_amount / sum(total_amount) * 100 )

hogan_category_totals
alsobrooks_filtered_data <- final_data |>
  filter(committee_name %in% c("ALSOBROOKS FOR SENATE"))

large_donation_threshold <- 1000

alsobrooks_category_totals <- alsobrooks_filtered_data |>
  mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
  group_by(donation_category) |>
  summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")

alsobrooks_category_totals  %>% mutate( percentage = total_amount / sum(total_amount) * 100 )

alsobrooks_category_totals

A5: Here we see that Hogan receives signficantly more money in general in comparison to Alsobrooks. Additionally, Hogan receives many more large donations (in excess of millions) in comparison to Alsobrooks. Whereas, the small donations are around 600,000 more. This shows that eithe Hogan has a larger “fan base” of people who donate to him or perhaps his electorate is just wealthier. Additionally,it would be interesting to note whether Hogan has a higher amount of donations because he was known before.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUiBOb3RlYm9vawpRdWVzdGlvbnMsIHJlZmluZWQ6CgpEbyBtb3JlIE1hcnlsYW5kZXJzIGRvbmF0ZSB0byBpbi1zdGF0ZSBvciBvdXQtb2Ytc3RhdGUgY2FuZGlkYXRlcz8gV2hpY2ggb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXMgcmVjZWl2ZWQgdGhlIG1vc3QgZG9uYXRpb25zIGFuZCB0aGUgZ3JlYXRlc3QgYW1vdW50IG9mIG1vbmV5IGluIGRvbmF0aW9ucz8gV2hhdCBhcmUgdGhlIGRlbW9ncmFwaGljcyBvZiBwZW9wbGUgd2hvIGRvbmF0ZSB0byBNYXJ5bGFuZCByYWNlcyBvbmx5PyBUbyBvdXQtb2Ytc3RhdGUgcmFjZXMgb25seT8gKHVzaW5nIHZvdGVyIGRhdGEgT1IgdXNpbmcgY2Vuc3VzIGRhdGEgdG8gc2VlIGlmIHRob3NlIGRvbm9ycyBhcmUgY2x1c3RlcmVkIGluIHNwZWNpZmljIGxvY2F0aW9ucywgYW5kLCBpZiB0aGV5IGFyZSwgd2hhdCB0aGUgbWFrZXVwcyBvZiB0aG9zZSBsb2NhdGlvbnMgYXJlKSBBbW9uZyB0b3AgTWFyeWxhbmQgZG9ub3JzLCB3aGF0IHByb2Zlc3Npb25zIGRvbmF0ZSB0aGUgbW9zdCBtb25leSB0byBzZW5hdGUgY2FtcGFpZ25zPyBXaGF04oCZcyB0aGUgbWFrZXVwIG9mIGRvbmF0aW9ucyByZWNlaXZlZCBieSBIb2dhbiBhbmQgQWxzb2Jyb29rcz8gV2hhdCBwZXJjZW50YWdlIG9mIHRoZWlyIG92ZXJhbGwgZG9uYXRpb25zIHdlcmUgbGFyZ2UgYW1vdW50cyBvZiBtb25leSAodG8gYmUgZGVmaW5lZCwgYnV0ID4gJDEwMDAsIGZvciBleGFtcGxlKSB2cyBzbWFsbCBhbW91bnRzPyBXaGljaCBwYXJ0eSB0ZW5kcyB0byBkb25hdGUgbW9yZSB0byBvdXQtb2Ytc3RhdGUgcmFjZXM/CgpXZSByZWZpbmVkIG91ciBkYXRhc2V0IGZ1cnRoZXIgYnkgZGVjaWRpbmcgdG8gZm9jdXMgb24gaW5kaXZpZHVhbCBkb25hdGlvbnMgbWFkZSB0byBzZW5hdGUgcmFjZXMgYnkgZG9ub3JzIGluIE1hcnlsYW5kLiBVc2luZyB0aGUgRkVDIHdlYnNpdGUsIHdlIGRvd25sb2FkZWQgYSBkYXRhc2V0IHRoYXQgbWV0IHRob3NlIHBhcmFtZXRlcnMuIFdlIGNsZWFuZWQgdGhlIGRhdGEgYnkgcmVtb3ZpbmcgdW5uZWNlc3NhcnkgY29sdW1ucyBhbmQgcmVuYW1pbmcgdGhlIGNvbHVtbnMgd2hlcmUgbmVlZGVkLiBXZSBkZWNpZGVkIHRvIGxpbWl0IG91ciBkYXRhc2V0IHRvIGRvbmF0aW9ucyBtYWRlIGluIDIwMjQgdG8gZW5zdXJlIHRoYXQgdGhlIGRvbmF0aW9ucyB3ZXJlIG1hZGUgYWZ0ZXIgdGhlIHByaW1hcnkgYW5kIGJlZm9yZSB0aGUgZ2VuZXJhbCBlbGVjdGlvbi4gV2UgaG9wZWQgdGhpcyB3b3VsZCBsaW1pdCB0aGUgbnVtYmVyIG9mIGNhbmRpZGF0ZXMgcmVjZWl2aW5nIGRvbmF0aW9ucywgc2luY2UgbW9zdCBkb25hdGlvbnMgd2lsbCBnbyB0b3dhcmQgb25lIG9mIHR3byBwYXJ0aWVzIGluIGEgY2VydGFpbiByYWNlLgoKV2UgYWxzbyBjbGVhbmVkIHRoZSBkYXRhLXNldCwgcmVtb3ZpbmcgbnVtZXJvdXMgY29sdW1ucyB0aGF0IHdlcmUgTi9BIG9yIHRoYXQgd2VyZSB1bm5lY2Vzc2FyeSB0byBvdXIgcHJvamVjdC4gV2UgYWxzbyBoYWQgdG8gcmVuYW1lIG9uZSBjb2x1bW4gYW5kIHRoZW4gZmlsdGVyIHRvIG9ubHkgdGhlIHJlcG9ydCB5ZWFyIG9mIDIwMjQgdG8gbGltaXQgdGhlIGRvbmF0aW9ucy4gVG8gYW5zd2VyIG91ciBmaXJzdCBxdWVzdGlvbiBhbmQgcXVlc3Rpb25zLCB3ZeKAmWxsIG5lZWQgdG8gc2VwYXJhdGUgdGhlIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIGZyb20gaW4tc3RhdGUgY2FuZGlkYXRlcywgYnV0IHRoaXMgc2hvdWxkIGJlIGVhc3kgYmVjYXVzZSB3ZeKAmWxsIGp1c3QgbmVlZCB0byBmaWx0ZXIgb3V0IHRoZSBIb2dhbiBhbmQgQWxzb2Jyb29rcyBjb21taXR0ZWVzIHRvIGlzb2xhdGUgdGhlIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIHJlY2VpdmluZyBkb25hdGlvbnMuIFRvIGFuc3dlciBvdXIgdGhpcmQgcXVlc3Rpb24sIHdl4oCZbGwgbmVlZCB0byBlaXRoZXIgY2FsbCBpbiBkZW1vZ3JhcGhpYyBkYXRhIGZyb20gdGhlIGNlbnN1cyBvciBpZGVudGlmeSBzcGVjaWZpYyBsb2NhdGlvbnMgd2l0aCBjbHVzdGVycyBvZiBkb25hdGlvbnMsIGFuZCBsb29rIHVwIGluZm9ybWF0aW9uIGFib3V0IHRob3NlIGxvY2F0aW9ucyB1c2luZyBjZW5zdXMuZ292LiBRdWVzdGlvbiAjNCBhc2tzIGFib3V0IHRoZSBwcm9mZXNzaW9ucyBvZiBkb25vcnMuIE9uZSBvYnZpb3VzIGNoYWxsZW5nZSBoZXJlIGlzIHRoYXQgcHJvZmVzc2lvbnMgYW5kIHRpdGxlcyBhcmUgb2Z0ZW4gc3BlbGxlZCBvciB3b3JkZWQgZGlmZmVyZW50bHksIGV2ZW4gaWYgdGhleSBkZXNjcmliZSB0aGUgc2FtZSBqb2LigJMgaW4gdGhpcyBkYXRhc2V0LCB0aGVyZSBhcmUgMiw3MzggZGlmZmVyZW50IHByb2Zlc3Npb25zIGxpc3RlZC4gVG8gdHJ5IHRvIGNvbWJhdCB0aGlzLCB3ZSB3aWxsIHVzZSBvcGVuIHJlZmluZSB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBvY2N1cGF0aW9ucyB3aXRoIHNsaWdodCB2YXJpYXRpb25zIGluIHNwZWxsaW5nIG9yIHdvcmRpbmcuIFdlIHdpbGwgdGhlbiBsaW1pdCB0aGUgZGF0YSBzZXQgdG8gdGhlIHRvcCAxMDAwIGRvbmF0aW9ucyB0byBtYWtlIHRoZSBhbmFseXNpcyBtb3JlIG1hbmFnZWFibGUuIFdlIGNhbiBhbHNvIG1ha2Ugc29tZSBicm9hZCBvYnNlcnZhdGlvbnMgYWJvdXQgdGhlIGRhdGEgZXZlbiB3aXRob3V0IGNsZWFuaW5nIHRoZSBwcm9mZXNzaW9uc+KAkyBmb3IgZXhhbXBsZSwgaXTigJlzIG9idmlvdXMgdGhhdCB0aGUgbW9zdCBkb25hdGlvbnMgY29tZSBmcm9tIHBlb3BsZSB3aG8gc2F5IHRoZXkgYXJlIOKAnG5vdCBlbXBsb3llZOKAnSAoNDU1NjgpIG9yIOKAnHJldGlyZWTigJ0gKDI5NDI0KS4gVGhlIG5leHQgaGlnaGVzdCBudW1iZXIgb2YgZG9uYXRpb25zIGlzIG1vcmUgdGhhbiAyMCwwMDAgZG9uYXRpb25zIGxlc3MgdGhhbiB0aGUgbnVtYmVyIG9mIGRvbmF0aW9ucyBmcm9tIHJldGlyZWQgcGVvcGxlLiBUaGVyZSBhcmUgMjA3IGNvbW1pdHRlZXMgdGhhdCByZWNlaXZlZCBkb25hdGlvbnMgaW4gb3VyIGRhdGFzZXQuIE9yaWdpbmFsbHksIHdlIHRob3VnaHQgdGhhdCB3ZSB3b3VsZCB1c2Ugb3BlbiByZWZpbmUgdG8gc29ydCB0aGUgY29tbWl0dGVlcyBieSBjYW5kaWRhdGUgbmFtZSwgYmVjYXVzZSB3ZSB0aG91Z2h0IHRoYXQgbW9zdCBjYW5kaWRhdGVzIHdvdWxkIGhhdmUgbXVsdGlwbGUgY29tbWl0dGVlcy4gSG93ZXZlciwgd2UgZm91bmQgdGhhdCB0aGlzIHdhcyBhY3R1YWxseSBwcmV0dHkgdW5jb21tb24sIGFuZCB3ZSB3ZXJlbuKAmXQgYWJsZSB0byBtYXRjaCBhbnkgbmFtZXMgdXNpbmcgb3BlbiByZWZpbmUsIG9uY2Ugd2UgdXBsb2FkZWQgb3VyIGNzdi4gRm9yIHF1ZXN0aW9uIDUsIHdlIG5lZWQgdG8gZG8gc29tZSBleHRyYSByZXNlYXJjaCB0byBkZWNpZGUgaG93IHRvIGRlZmluZSBsYXJnZSBkb25hdGlvbnMuIE9uZSBpZGVhIGlzIHRvIGZpbmQgdGhlIGF2ZXJhZ2Ugb3IgbWVkaWFuIGRvbmF0aW9uLCBhbmQgdXNlIHRoYXQgbnVtYmVyIGFzIHRoZSBkaXZpZGluZyBsaW5lIGJldHdlZW4gc21hbGwgYW5kIGxhcmdlIGRvbmF0aW9ucy4gQW5vdGhlciBpZGVhIGlzIHRvIHNlZSBpZiB0aGVyZeKAmXMgYW4gYWdyZWVkLXVwb24gZGVmaW5pdGlvbiBieSBwZW9wbGUgd2hvIHdvcmsgb24gY2FtcGFpZ25zIG9yIHBvbGl0aWNhbCBzY2llbnRpc3RzLiBXZSBoYXZlIG9uZSBleHRyYSBxdWVzdGlvbiAoIzYpIHRoYXQgd2Ugd291bGQgbGlrZSB0byBhbnN3ZXIsIGJ1dCBpdCBpbnZvbHZlcyBwYXJ0eS1sZXZlbCBhbmFseXNpcyB0aGF0IHdlIGNhbuKAmXQgZG8gYmVjYXVzZSB3ZSBkb27igJl0IGhhdmUgdGhlIHBvbGl0aWNhbCBwYXJ0aWVzIG9mIHRoZSBkb25vcnMgaW4gdGhpcyBkYXRhLCBhbmQgd2UgZG9u4oCZdCBoYXZlIGFueXRoaW5nIGluIHRoaXMgZGF0YSB0aGF0IGluZGljYXRlcyB0aGUgcGFydHkgb2YgZWFjaCBjYW5kaWRhdGUuIFRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCB3ZSBjb3VsZCBqb2luIHRoaXMgZGF0YSB3aXRoIGRhdGEgZnJvbSBBY3QgQmx1ZSBhbmQgV2luIFJlZCB0byBpZGVudGlmeSB0aGUgcGFydGllcyBvZiBkb25vcnMuIFdlIGNhbiBhbHNvIHByb2JhYmx5IGZpbmQgYSBkYXRhc2V0IHdpdGggdGhlIGNvbW1pdHRlZSBuYW1lcyBhbmQgcGFydGllcyBmb3IgYWxsIHNlbmF0ZSBjYW5kaWRhdGVzLCBhbmQgam9pbiB0aGF0IGRhdGFzZXQgd2l0aCBvdXJzLgoKIyBUdXJuIG9mZiBzY2llbnRpZmljIG5vdGF0aW9uCgpgYGB7cn0Kb3B0aW9ucyhzY2lwZW49OTk5KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCgoKYGBgCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygndGlkeWNlbnN1cycpCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeWNlbnN1cykKYGBgCgoKCmBgYHtyfQptZF9zZW5hdGVfY29udHJpYnV0aW9ucyA8LSByZWFkX2NzdigiZGF0YS9tZF9zZW5hdGVfY29udHJpYnV0aW9ucy5jc3YiKSB8PgoKCnByaW50KGNvbHVtbl9uYW1lcykKYGBgCgojY2xlYW4gZGF0YQpgYGB7cn0KY2xlYW5lZF9kYXRhIDwtIG1kX3NlbmF0ZV9jb250cmlidXRpb25zIHw+CgpzZWxlY3QoIC11bnVzZWRfY29udGJyX2lkLCAtY29tbWl0dGVlX25hbWUuLi45LCAtcmVjaXBpZW50X2NvbW1pdHRlZV9vcmdfdHlwZSwgLWNvbnRyaWJ1dG9yX3N1ZmZpeCwgLWNvbnRyaWJ1dG9yX3N0cmVldF8yLCAtY29udHJpYnV0b3JfaWQsIC1tZW1vX2NvZGUsIC1tZW1vX2NvZGVfZnVsbCwgLWNhbmRpZGF0ZV9pZCwgLWNhbmRpZGF0ZV9uYW1lLCAtY2FuZGlkYXRlX2ZpcnN0X25hbWUsIC1jYW5kaWRhdGVfbGFzdF9uYW1lLCAtY2FuZGlkYXRlX21pZGRsZV9uYW1lLCAtY2FuZGlkYXRlX3ByZWZpeCwgLWNhbmRpZGF0ZV9zdWZmaXgsIC1jYW5kaWRhdGVfb2ZmaWNlLCAtY2FuZGlkYXRlX29mZmljZV9mdWxsLCAtY2FuZGlkYXRlX29mZmljZV9zdGF0ZSwgLWNhbmRpZGF0ZV9vZmZpY2Vfc3RhdGVfZnVsbCwgLWNhbmRpZGF0ZV9vZmZpY2VfZGlzdHJpY3QsIC1jb25kdWl0X2NvbW1pdHRlZV9pZCwgLWNvbmR1aXRfY29tbWl0dGVlX25hbWUsIC1jb25kdWl0X2NvbW1pdHRlZV9zdHJlZXQxLCAtY29uZHVpdF9jb21taXR0ZWVfc3RyZWV0MiwgLWNvbmR1aXRfY29tbWl0dGVlX2NpdHksIC1jb25kdWl0X2NvbW1pdHRlZV9zdGF0ZSwgLWNvbmR1aXRfY29tbWl0dGVlX3ppcCwgLWRvbm9yX2NvbW1pdHRlZV9uYW1lLCAtbmF0aW9uYWxfY29tbWl0dGVlX25vbmZlZGVyYWxfYWNjb3VudCwgLWVsZWN0aW9uX3R5cGVfZnVsbCwgLWluY3JlYXNlZF9saW1pdCwgLWlzX2luZGl2aWR1YWwpIHw+CgpyZW5hbWUoY29tbWl0dGVlX25hbWUgPSBgY29tbWl0dGVlX25hbWUuLi4yYCkgfD4KCmZpbHRlcihyZXBvcnRfeWVhciA9PSAyMDI0KQoKCmNvbG5hbWVzKGNsZWFuZWRfZGF0YSkKYGBgCgpgYGB7cn0KbW9zdF9jb250cmlidXRpb25zIDwtIGNsZWFuZWRfZGF0YSB8PgpzZWxlY3QoY29tbWl0dGVlX25hbWUsIGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCkgfD4KZ3JvdXBfYnkoY29tbWl0dGVlX25hbWUpIHw+CnN1bW1hcml6ZSh0b3RhbF9jb250cmlidXRpb24gPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpKSB8PgphcnJhbmdlKGRlc2ModG90YWxfY29udHJpYnV0aW9uKSkgCmNsZWFuZWRfZGF0YSB8PgogIAp3cml0ZV9jc3YoImRhdGEvY2xlYW5lZF9tZF9zZW5hdGVfY29udHJpYnV0aW9ucy5jc3YiKQpkYXRhIDwtIHJlYWRfZGVsaW0oImRhdGEvY2NsLnR4dCIsIGRlbGltID0gInwiLCBjb2xfbmFtZXMgPSBGQUxTRSkKCmNsZWFuZWRfZGF0YV9jY2wgPC0gZGF0YSB8PgpyZW5hbWUoY2FuZGlkYXRlX2lkID0gWDEsY2FuZGlkYXRlX2VsZWN0aW9uX3llYXIgPSBYMiwgZmVjX2VsZWN0aW9uX3llYXIgPSBYMywgY29tbWl0dGVlX2lkID0gWDQsY29tbWl0dGVlX3R5cGUgPSBYNSxjb21taXR0ZWVfZGVzaWduID0gWDYsIGxpbmthZ2VfaWQgPSBYNykKYGBgCgojaW5uZXIgam9pbiB0aGUgY29tbWl0dGVlIGlkIGFuZCBmZWMgZWxlY3Rpb24geWVhciAKCmBgYHtyfQpqb2luZWRfZGF0YSA8LSBpbm5lcl9qb2luKGNsZWFuZWRfZGF0YSwgY2xlYW5lZF9kYXRhX2NjbCwgYnkgPSBjKCJjb21taXR0ZWVfaWQiLCAiZmVjX2VsZWN0aW9uX3llYXIiKSkKYGBgCgojaW5zZXJ0IHRoZSBjYW5kaWRhdGUgZGF0YQpgYGB7cn0KY2FuZGlkYXRlX2RhdGEgPC0gcmVhZF9kZWxpbSgiZGF0YS9jYW5kaWRhdGVfZGF0YS50eHQiLCBkZWxpbSA9ICJ8IiwgY29sX25hbWVzID0gRkFMU0UpIHw+CiAgc2VsZWN0KFgxLCBYMiwgWDMsIFg1KSB8PiAKIHJlbmFtZShjYW5kaWRhdGVfaWQgPSBYMSwgY2FuZGlkYXRlX25hbWUgPSBYMiwgY2FuZGlkYXRlX3BhcnR5ID0gWDUpCgpjYW5kaWRhdGVfam9pbmVkX2RhdGEgPC0gaW5uZXJfam9pbihqb2luZWRfZGF0YSwgY2FuZGlkYXRlX2RhdGEsIGJ5ID1jKCJjYW5kaWRhdGVfaWQiKSkKYGBgCgoKI2luY2x1ZGUgb25seSB0aGVzZSByb3dzIAoKYGBge3J9CgpmaW5hbF9kYXRhIDwtIGNhbmRpZGF0ZV9qb2luZWRfZGF0YSB8PgpzZWxlY3QoY29tbWl0dGVlX2lkLCBjb21taXR0ZWVfbmFtZSwgcmVwb3J0X3llYXIsIGVudGl0eV90eXBlX2Rlc2MsY29udHJpYnV0b3JfcHJlZml4LCBjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl9maXJzdF9uYW1lLCBjb250cmlidXRvcl9sYXN0X25hbWUsIGNvbnRyaWJ1dG9yX21pZGRsZV9uYW1lLCBjb250cmlidXRvcl9zdHJlZXRfMSxjb250cmlidXRvcl9jaXR5LCBjb250cmlidXRvcl9zdGF0ZSwgY29udHJpYnV0b3JfemlwLGNvbnRyaWJ1dG9yX2VtcGxveWVyLCBjb250cmlidXRvcl9vY2N1cGF0aW9uLCBjb250cmlidXRpb25fcmVjZWlwdF9kYXRlLCBjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQsIGNvbnRyaWJ1dG9yX2FnZ3JlZ2F0ZV95dGQsbWVtb190ZXh0LHBkZl91cmwsIGNhbmRpZGF0ZV9pZCwgY2FuZGlkYXRlX2VsZWN0aW9uX3llYXIpCmBgYAoKUTE6IERvIG1vcmUgTWFyeWxhbmRlcnMgZG9uYXRlIHRvIGluLXN0YXRlIG9yIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzPyAKCmBgYHtyfQpmaW5hbF9kYXRhX3N0YXRlcyA8LSBmaW5hbF9kYXRhIHw+CiAgbXV0YXRlKHN0YXRlID0gc3Vic3RyKGNhbmRpZGF0ZV9pZCwgMywgNCkpCmBgYAoKYGBge3J9CnN0YXRlX2NvbnRyaWJ1dGlvbnMgPC0gZmluYWxfZGF0YV9zdGF0ZXMgfD4KICBncm91cF9ieShzdGF0ZSkgfD4KICBzdW1tYXJpc2UoCiAgICBjb250cmlidXRpb25fY291bnQgPSBuKCksICAgICAgICAgICAgICAgIAogICAgdG90YWxfY29udHJpYnV0aW9uID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSAgCiAgKQpgYGAKCmBgYHtyfQptYXJ5bGFuZF9jb250cmliIDwtIHN0YXRlX2NvbnRyaWJ1dGlvbnMgfD4KICBmaWx0ZXIoc3RhdGUgPT0gIk1EIikgfD4KICBzdW1tYXJpc2UodG90YWxfbWFyeWxhbmRfY29udHJpYiA9IHN1bSh0b3RhbF9jb250cmlidXRpb24sIG5hLnJtID0gVFJVRSkpCgoKb3RoZXJfc3RhdGVzX2NvbnRyaWIgPC0gc3RhdGVfY29udHJpYnV0aW9ucyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKSB8PgogIHN1bW1hcmlzZSh0b3RhbF9vdGhlcl9zdGF0ZXNfY29udHJpYiA9IHN1bSh0b3RhbF9jb250cmlidXRpb24sIG5hLnJtID0gVFJVRSkpCgoKY29tcGFyaXNvbiA8LSBkYXRhLmZyYW1lKAogIHN0YXRlID0gYygiTWFyeWxhbmQiLCAiT3RoZXIgU3RhdGVzIiksCiAgdG90YWxfY29udHJpYnV0aW9uID0gYyhtYXJ5bGFuZF9jb250cmliJHRvdGFsX21hcnlsYW5kX2NvbnRyaWIsIG90aGVyX3N0YXRlc19jb250cmliJHRvdGFsX290aGVyX3N0YXRlc19jb250cmliKQopCmBgYAoKCkE6IE1vbnRhbmEgd2FzIHN1cnByaXNpbmdseSB0aGUgc3RhdGUgd2l0aCB0aGUgbW9zdCBjb250cmlidXRpb25zIC0tLSBlZGdpbmcgTWFyeWxhbmQgd2l0aCAyMDIgbW9yZSBjb250cmlidXRpb25zIE1hcnlsYW5kLiBNYXJ5bGFuZCByZWNlaXZlZCB0aGUgaGlnaGVzdCB0b3RhbCBzdW0gaG93ZXZlciwgd2l0aCAkNSw1MTYsNTYyLjI0LiBUaGF0IHdhcyAkNCwwNzQsMjI2LjA3IG1vcmUgdGhhbiB0aGUgbmV4dCBoaWdoZXN0IHN0YXRlLCB3aGljaCB3YXMgTW9udGFuYS4gVGhlIG90aGVyIHN0YXRlcyBjb21iaW5lZCByZWNpZXZlZCAkNywzNTgsOTcwLCBhIGxpdHRsZSBsZXNzIHRoYW4gdHdvIG1pbGxpb24gbW9yZSB0aGFuIGp1c3QgdGhlIHN0YXRlIG9mIE1hcnlsYW5kLiAKCgpRMjogV2hpY2ggb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXMgcmVjZWl2ZWQgdGhlIG1vc3QgZG9uYXRpb25zIGFuZCB0aGUgZ3JlYXRlc3QgYW1vdW50IG9mIG1vbmV5IGluIGRvbmF0aW9ucz8gCgpgYGB7cn0KZmluYWxfZGF0YV9ub19tZCA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKQpgYGAKCmBgYHtyfQpjb250cmlidXRpb25zX3N1bW1hcnkgPC0gZmluYWxfZGF0YV9ub19tZCB8PgogIGdyb3VwX2J5KGNvbW1pdHRlZV9uYW1lKSB8PgogIHN1bW1hcmlzZSgKICAgIG51bV9jb250cmlidXRpb25zID0gbigpLCAKICAgIHRvdGFsX2NvbnRyaWJ1dGlvbl9zdW0gPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpIAogICkgfD4KICBhcnJhbmdlKGNvbW1pdHRlZV9uYW1lKQpgYGAKCkEyOiBKb24gVGVzdGVyLCBTaGVycm9kIEJyb3duIGFuZCBSdWJlbiBHYWxsZWdvIHdlcmUgdGhlIHRvcCB0aHJlZSBpbiB0aGF0IG9yZGVyIGZvciBib3RoIGNvbnRyaWJ1dGlvbnMgcmVjaWV2ZWQgYW5kIHRoZSBzdW0gb2YgY29udHJpYnV0aW9ucy4gVGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgdGhyZWUgb2YgdGhlbSBpcyB0aGF0IHRoZXkgd2VyZSBhbGwgRGVtb2NyYXRzIHJ1bm5pbmcgaW4gdGlnaHRseSBjb250ZXN0ZWQgcmFjZXMuIEJyb3duIHdhcyB0aGUgb25seSB0byBsb3NlIGhpcyByYWNlLiBKb24gVGVzdGVyIGFsc28gY2xlYXJseSByZWNpZXZlZCBtb3JlIHRoYW4gdGhlIG90aGVyIHR3byAtLS0gd2hpY2ggZXhwbGFpbnMgd2h5IE1vbnRhbmEgcmVjZWl2ZWQgc28gbWFueSBtb3JlIG91dC1vZi1zdGF0ZSBjb250cmlidXRpb25zIHRoYW4gb3RoZXIgc3RhdGVzLiBNb250YW5hbnMgZm9yIFRlc3RlciByZWNlaXZlZCAzLDY3OSBtb3JlIGNvbnRyaWJ1dGlvbnMgYW5kICQyMzgsMDE3Ljk2IG1vcmUgaW4gdG90YWwgY29udHJpYnV0aW9ucyBjb21wYXJlZCB0byBGcmllbmRzIG9mIFNoZXJyb2QgQnJvd24uCgpRMzogV2hhdCBhcmUgdGhlIGRlbW9ncmFwaGljcyBvZiBwZW9wbGUgd2hvIGRvbmF0ZSB0byBNYXJ5bGFuZCByYWNlcyBvbmx5PyBUbyBvdXQtb2Ytc3RhdGUgcmFjZXMgb25seT8KClN0ZXAgMTogZmluZCBwZW9wbGUgd2hvIGRvbmF0ZSB0byBPTkxZIE1hcnlsYW5kIHJhY2VzLgpgYGB7cn0KCm1hcnlsYW5kX29ubHlfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzfD4KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSB8PiAgICAgICAgICAgICAgICAKICBzdW1tYXJpemUob25seV9tZCA9IGFsbChzdGF0ZSA9PSAiTUQiKSkgfD4KICBmaWx0ZXIob25seV9tZCkgfD4gICAgICAgICAgICAgICAgICAgICAgICAgIAogIHNlbGVjdChjb250cmlidXRvcl9uYW1lKSAgICAgICAgICAgICAgICAgICAgCgpmdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzIHw+CiAgIGZpbHRlcihjb250cmlidXRvcl9uYW1lICVpbiUgbWFyeWxhbmRfb25seV9kb25vcnMkY29udHJpYnV0b3JfbmFtZSkKCgp6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgPC0gZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUsIGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50KSAKICApfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpICAKCm1kX3ppcF9zdW1tYXJ5IDwtIHppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4gICAgICAgICAgICAgIAogIHN1bW1hcml6ZSgKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAgICAgICAgICAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGVkKSAgICAgIAogICkgfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpIAoKYGBgCmBgYHtyfQphbGxfemN0YSA8LSBnZXRfYWNzKAogIGdlb2dyYXBoeSA9ICJ6Y3RhIiwKICB2YXJpYWJsZXMgPSBjKAogIkIwMTAwM18wMDEiLCAKICAgICAiQjAxMDAyXzAwMSIsICM9ICJtZWRpYW5fYWdlIiwKICJCMTkwMTNfMDAxIiwgIyA9ICJtZWRpYW5faW5jb21lIiwKICAiQjAyMDAxXzAwMiIsICMgPSAid2hpdGVfYWxvbmUiLAogICAgICJCMDIwMDFfMDAzIiwgIyA9ICJibGFja19hbG9uZSIsCiJCMDIwMDFfMDA0IiwgIyA9ICJuYXRpdmVfYW1lcmljYW4iLAogICAgIkIwMjAwMV8wMDUiLCAjPSAiYXNpYW5fYWxvbmUiLAogIkIwMjAwMV8wMDYiLCAjID0gImhhd2FpaWFuX3BhY2lmaWMiLAoiQjAyMDAxXzAwNyIsICAjID0gIm90aGVyX3JhY2UiLAogICAgIkIwMjAwMV8wMDgiLCAjID0gInR3b19vcl9tb3JlX3JhY2VzIgoiQjAzMDAyXzAxMkUiKSwKICAKICB5ZWFyID0gMjAyMiwKICBzdXJ2ZXkgPSAiYWNzNSIsCiAgb3V0cHV0ID0gIndpZGUiCikKCmFsbF96Y3RhIDwtIGFsbF96Y3RhICU+JQogIHJlbmFtZSgKICAgIHRvdGFsX3BvcHVsYXRpb24gPSBCMDEwMDNfMDAxRSwgICAgICAKICAgIG1lZGlhbl9hZ2UgPSBCMDEwMDJfMDAxRSwgICAgICAgICAgICAKICAgIG1lZGlhbl9pbmNvbWUgPSBCMTkwMTNfMDAxRSwgICAgICAgIAogICAgd2hpdGVfYWxvbmUgPSBCMDIwMDFfMDAyRSwgICAgICAgICAgCiAgICBibGFja19hbG9uZSA9IEIwMjAwMV8wMDNFLCAgICAgICAgIAogICAgbmF0aXZlX2FtZXJpY2FuID0gQjAyMDAxXzAwNEUsICAgICAgCiAgICBhc2lhbl9hbG9uZSA9IEIwMjAwMV8wMDVFLCAgICAgICAgICAKICAgIGhhd2FpaWFuX3BhY2lmaWMgPSBCMDIwMDFfMDA2RSwgICAgIAogICAgb3RoZXJfcmFjZSA9IEIwMjAwMV8wMDdFLCAgICAgICAgICAgCiAgICB0d29fb3JfbW9yZV9yYWNlcyA9IEIwMjAwMV8wMDhFLAogICAgaGlzcGFuaWNfb3JfbGF0aW5vID0gQjAzMDAyXzAxMkUKICApCgpgYGAKYGBge3J9Cgp6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgPC0gemlwc19mdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIHw+CiAgbXV0YXRlKAogICAgY29udHJpYnV0b3JfemlwID0gc3Vic3RyKGNvbnRyaWJ1dG9yX3ppcCwgMSwgNSksCiAgICBjb250cmlidXRvcl96aXAgPSBzcHJpbnRmKCIlMDVzIiwgY29udHJpYnV0b3JfemlwKQogICkKCnppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyA8LSB6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgfD4KICBtdXRhdGUoY29udHJpYnV0b3JfemlwID0gYXMuY2hhcmFjdGVyKGNvbnRyaWJ1dG9yX3ppcCkpCgptZXJnZWRfZGF0YV9tZCA8LSB6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgJT4lCiAgbGVmdF9qb2luKGFsbF96Y3RhLCBieSA9IGMoImNvbnRyaWJ1dG9yX3ppcCIgPSAiR0VPSUQiKSkKCnN1bW1hcml6ZWRfbWRfZG9ub3JfZGVtb3NfYnlfemlwIDwtIG1lcmdlZF9kYXRhX21kICU+JQogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICB0b3RhbF9wb3B1bGF0aW9uID0gZmlyc3QodG90YWxfcG9wdWxhdGlvbiksICAKICAgIG1lZGlhbl9hZ2UgPSBmaXJzdChtZWRpYW5fYWdlKSwgICAgICAgICAgICAgCiAgICBtZWRpYW5faW5jb21lID0gZmlyc3QobWVkaWFuX2luY29tZSksICAgICAgIAogICAgd2hpdGVfYWxvbmUgPSBmaXJzdCh3aGl0ZV9hbG9uZSksICAgICAgICAgICAgCiAgICBibGFja19hbG9uZSA9IGZpcnN0KGJsYWNrX2Fsb25lKSwgICAgICAgICAgIAogICAgbmF0aXZlX2FtZXJpY2FuID0gZmlyc3QobmF0aXZlX2FtZXJpY2FuKSwgICAKICAgIGFzaWFuX2Fsb25lID0gZmlyc3QoYXNpYW5fYWxvbmUpLCAgICAgICAgICAgCiAgICBoYXdhaWlhbl9wYWNpZmljID0gZmlyc3QoaGF3YWlpYW5fcGFjaWZpYyksICAKICAgIG90aGVyX3JhY2UgPSBmaXJzdChvdGhlcl9yYWNlKSwgIAogICAgIGhpc3BhbmljX29yX2xhdGlubyA9IGZpcnN0KGhpc3BhbmljX29yX2xhdGlubyksCiAgICB0d29fb3JfbW9yZV9yYWNlcyA9IGZpcnN0KHR3b19vcl9tb3JlX3JhY2VzKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAgICAgICAgICAgICAgICAgICAgIAogICAgdG90YWxfYW10X2RvbmF0ZWQgPSBzdW0odG90YWxfZG9uYXRlZCwgbmEucm0gPSBUUlVFKSAKICApIHw+IAogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgIHw+IAogIG11dGF0ZSgKICAgIHdoaXRlX2Fsb25lX3Blcl9jYXBpdGEgPSB3aGl0ZV9hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBibGFja19hbG9uZV9wZXJfY2FwaXRhID0gYmxhY2tfYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbmF0aXZlX2FtZXJpY2FuX3Blcl9jYXBpdGEgPSBuYXRpdmVfYW1lcmljYW4gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgYXNpYW5fYWxvbmVfcGVyX2NhcGl0YSA9IGFzaWFuX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGhhd2FpaWFuX3BhY2lmaWNfcGVyX2NhcGl0YSA9IGhhd2FpaWFuX3BhY2lmaWMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgb3RoZXJfcmFjZV9wZXJfY2FwaXRhID0gb3RoZXJfcmFjZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICAgaGlzcGFuaWNfb3JfbGF0aW5vX3Blcl9jYXBpdGEgPSBoaXNwYW5pY19vcl9sYXRpbm8gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgdHdvX29yX21vcmVfcmFjZXNfcGVyX2NhcGl0YSA9IHR3b19vcl9tb3JlX3JhY2VzIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSA9IG1lZGlhbl9pbmNvbWUgLyB0b3RhbF9wb3B1bGF0aW9uCiAgKSB8PgogICBtdXRhdGUoCiAgICB3aGl0ZV9hbG9uZV9wZXJjZW50ID0gd2hpdGVfYWxvbmVfcGVyX2NhcGl0YSAqIDEwMCwKICAgIGJsYWNrX2Fsb25lX3BlcmNlbnQgPSBibGFja19hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgbmF0aXZlX2FtZXJpY2FuX3BlcmNlbnQgPSBuYXRpdmVfYW1lcmljYW5fcGVyX2NhcGl0YSAqIDEwMCwKICAgIGFzaWFuX2Fsb25lX3BlcmNlbnQgPSBhc2lhbl9hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgaGF3YWlpYW5fcGFjaWZpY19wZXJjZW50ID0gaGF3YWlpYW5fcGFjaWZpY19wZXJfY2FwaXRhICogMTAwLAogICAgb3RoZXJfcmFjZV9wZXJjZW50ID0gb3RoZXJfcmFjZV9wZXJfY2FwaXRhICogMTAwLAogICAgaGlzcGFuaWNfb3JfbGF0aW5vX3BlcmNlbnQgPSBoaXNwYW5pY19vcl9sYXRpbm9fcGVyX2NhcGl0YSAqMTAwLAogICAgdHdvX29yX21vcmVfcmFjZXNfcGVyY2VudCA9IHR3b19vcl9tb3JlX3JhY2VzX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBtZWRpYW5faW5jb21lX3Blcl9jYXBpdGEgPSBtZWRpYW5faW5jb21lX3Blcl9jYXBpdGEgKiAxMDAKICApIHw+CiBtdXRhdGUoCiAgICBhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQgPSB0b3RhbF9hbXRfZG9uYXRlZCAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+ICAgCiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQoKCmBgYApgYGB7cn0KCmNsZWFuZXJfbWRfZG9ub3JfZGVtb3MgPC0gc3VtbWFyaXplZF9tZF9kb25vcl9kZW1vc19ieV96aXAgfD4gCiAgICBzZWxlY3QoLW1hdGNoZXMoIl9wZXJfY2FwaXRhIiksIC0ibmF0aXZlX2FtZXJpY2FuIiwgLSJoYXdhaWlhbl9wYWNpZmljIiwgLSJvdGhlcl9yYWNlIiwgLSJ0d29fb3JfbW9yZV9yYWNlcyIsIC0id2hpdGVfYWxvbmUiLCAtImJsYWNrX2Fsb25lIiwgLSJhc2lhbl9hbG9uZSIpIAogCgoKYGBgCiNyZXBlYXQgZm9yIG91dCBvZiBzdGF0ZSBkb25vcnMgCgpgYGB7cn0Kb3V0X29mX3N0YXRlX2Rvbm9ycyA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSAhPSAiTUQiKQoKeG1hcnlsYW5kX2Rvbm9ycyA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGZpbHRlcihzdGF0ZSA9PSAiTUQiKQoKb3V0X29mX3N0YXRlX29ubHlfZG9ub3JzIDwtIG91dF9vZl9zdGF0ZV9kb25vcnMgfD4KICBmaWx0ZXIoIWNvbnRyaWJ1dG9yX25hbWUgJWluJSB4bWFyeWxhbmRfZG9ub3JzJGNvbnRyaWJ1dG9yX25hbWUpICB8Pgpncm91cF9ieShjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl96aXApIHw+CiAgc3VtbWFyaXplKAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50KSAgCiAgKSB8PgogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgIAoKCm91dF9vZl9zdGF0ZV9vbmx5X2Rvbm9ycyA8LSBvdXRfb2Zfc3RhdGVfb25seV9kb25vcnMgfD4KICBtdXRhdGUoCiAgICBjb250cmlidXRvcl96aXAgPSBzdWJzdHIoY29udHJpYnV0b3JfemlwLCAxLCA1KSwKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHNwcmludGYoIiUwNXMiLCBjb250cmlidXRvcl96aXApCiAgKQoKCmBgYApgYGB7cn0KCm1lcmdlZF9kYXRhX29vcyA8LSBvdXRfb2Zfc3RhdGVfb25seV9kb25vcnN8PgogIGxlZnRfam9pbihhbGxfemN0YSwgYnkgPSBjKCJjb250cmlidXRvcl96aXAiID0gIkdFT0lEIikpCgpjbGVhbmVyX29vc19kb25vcl9kZW1vcyA8LSBtZXJnZWRfZGF0YV9vb3MgIHw+CiAgIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICB0b3RhbF9wb3B1bGF0aW9uID0gZmlyc3QodG90YWxfcG9wdWxhdGlvbiksIAogICAgbWVkaWFuX2FnZSA9IGZpcnN0KG1lZGlhbl9hZ2UpLCAgICAgICAgICAgICAgCiAgICBtZWRpYW5faW5jb21lID0gZmlyc3QobWVkaWFuX2luY29tZSksICAgICAgICAKICAgIHdoaXRlX2Fsb25lID0gZmlyc3Qod2hpdGVfYWxvbmUpLCAgICAgICAgIAogICAgYmxhY2tfYWxvbmUgPSBmaXJzdChibGFja19hbG9uZSksICAgICAgICAgICAgCiAgICBuYXRpdmVfYW1lcmljYW4gPSBmaXJzdChuYXRpdmVfYW1lcmljYW4pLCAgIAogICAgYXNpYW5fYWxvbmUgPSBmaXJzdChhc2lhbl9hbG9uZSksICAgICAgICAgICAKICAgIGhhd2FpaWFuX3BhY2lmaWMgPSBmaXJzdChoYXdhaWlhbl9wYWNpZmljKSwKICAgIG90aGVyX3JhY2UgPSBmaXJzdChvdGhlcl9yYWNlKSwgICAgIAogICAgaGlzcGFuaWNfb3JfbGF0aW5vID0gZmlyc3QoaGlzcGFuaWNfb3JfbGF0aW5vKSwKICAgIHR3b19vcl9tb3JlX3JhY2VzID0gZmlyc3QodHdvX29yX21vcmVfcmFjZXMpLAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAgICAgICAgICAgCiAgICB0b3RhbF9hbXRfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGVkLCBuYS5ybSA9IFRSVUUpIAogICkgfD4gCiAgYXJyYW5nZShkZXNjKG51bV9kb25hdGlvbnMpKSAgfD4gCiAgbXV0YXRlKAogICAKICAgIHdoaXRlX2Fsb25lX3Blcl9jYXBpdGEgPSB3aGl0ZV9hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBibGFja19hbG9uZV9wZXJfY2FwaXRhID0gYmxhY2tfYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbmF0aXZlX2FtZXJpY2FuX3Blcl9jYXBpdGEgPSBuYXRpdmVfYW1lcmljYW4gLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgYXNpYW5fYWxvbmVfcGVyX2NhcGl0YSA9IGFzaWFuX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGhhd2FpaWFuX3BhY2lmaWNfcGVyX2NhcGl0YSA9IGhhd2FpaWFuX3BhY2lmaWMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgb3RoZXJfcmFjZV9wZXJfY2FwaXRhID0gb3RoZXJfcmFjZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyX2NhcGl0YSA9IGhpc3BhbmljX29yX2xhdGlubyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJfY2FwaXRhID0gdHdvX29yX21vcmVfcmFjZXMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbWVkaWFuX2luY29tZV9wZXJfY2FwaXRhID0gbWVkaWFuX2luY29tZSAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+CiAgIG11dGF0ZSgKICAKICAgIHdoaXRlX2Fsb25lX3BlcmNlbnQgPSB3aGl0ZV9hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgYmxhY2tfYWxvbmVfcGVyY2VudCA9IGJsYWNrX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBuYXRpdmVfYW1lcmljYW5fcGVyY2VudCA9IG5hdGl2ZV9hbWVyaWNhbl9wZXJfY2FwaXRhICogMTAwLAogICAgYXNpYW5fYWxvbmVfcGVyY2VudCA9IGFzaWFuX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoYXdhaWlhbl9wYWNpZmljX3BlcmNlbnQgPSBoYXdhaWlhbl9wYWNpZmljX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBvdGhlcl9yYWNlX3BlcmNlbnQgPSBvdGhlcl9yYWNlX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyY2VudCA9IGhpc3BhbmljX29yX2xhdGlub19wZXJfY2FwaXRhICoxMDAsCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJjZW50ID0gdHdvX29yX21vcmVfcmFjZXNfcGVyX2NhcGl0YSAqIDEwMCwKICAgIG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSA9IG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSAqIDEwMCAgCiAgKSAKCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIDwtIGNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IHNlbGVjdCgtbWF0Y2hlcygiX3Blcl9jYXBpdGEiKSwgLSJuYXRpdmVfYW1lcmljYW4iLCAtImhhd2FpaWFuX3BhY2lmaWMiLCAtIm90aGVyX3JhY2UiLCAtInR3b19vcl9tb3JlX3JhY2VzIiwgLSJ3aGl0ZV9hbG9uZSIsIC0iYmxhY2tfYWxvbmUiLCAtImFzaWFuX2Fsb25lIikgfD4gCiAgCiAgbXV0YXRlKAogICAgYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50ID0gdG90YWxfYW10X2RvbmF0ZWQgLyB0b3RhbF9wb3B1bGF0aW9uCiAgKSB8PgogIHNlbGVjdCh3aGVyZSh+ICFhbGwoaXMubmEoLikpKSkKCgpgYGAKYGBge3J9CmhlYWQobWVyZ2VkX2RhdGFfb29zKQpgYGAKCgpgYGB7cn0KY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgfD4gICAKICBtdXRhdGUoCiAgICBjb250cmlidXRvcl96aXAgPSBhcy5jaGFyYWN0ZXIoY29udHJpYnV0b3JfemlwKSwgICAgICAgICAjIEVuc3VyZSBaSVAgY29kZXMgYXJlIHN0cmluZ3MKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHN0cl9wYWQoY29udHJpYnV0b3JfemlwLCB3aWR0aCA9IDUsICAgICMgUGFkIHdpdGggbGVhZGluZyB6ZXJvcyB0byBlbnN1cmUgNSBkaWdpdHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lkZSA9ICJsZWZ0IiwgcGFkID0gIjAiKSwKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGlmZWxzZShzdHJfZGV0ZWN0KGNvbnRyaWJ1dG9yX3ppcCwgIl5cXGR7NX0kIiksICAjIEtlZXAgb25seSB2YWxpZCA1LWRpZ2l0IFpJUCBjb2RlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyaWJ1dG9yX3ppcCwgTkEpKQoKCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKSB8PiB3cml0ZV9jc3YoImNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zLmNzdiIpCgpgYGAKCmBgYHtyfQpjbGVhbmVyX21kX2Rvbm9yX2RlbW9zIHw+IAogIG11dGF0ZSgKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAgICAgICAgICMgRW5zdXJlIFpJUCBjb2RlcyBhcmUgc3RyaW5ncwogICAgY29udHJpYnV0b3JfemlwID0gc3RyX3BhZChjb250cmlidXRvcl96aXAsIHdpZHRoID0gNSwgICAgIyBQYWQgd2l0aCBsZWFkaW5nIHplcm9zIHRvIGVuc3VyZSA1IGRpZ2l0cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWRlID0gImxlZnQiLCBwYWQgPSAiMCIpLAogICAgY29udHJpYnV0b3JfemlwID0gaWZlbHNlKHN0cl9kZXRlY3QoY29udHJpYnV0b3JfemlwLCAiXlxcZHs1fSQiKSwgICMgS2VlcCBvbmx5IHZhbGlkIDUtZGlnaXQgWklQIGNvZGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJpYnV0b3JfemlwLCBOQSkpIHw+IAogIGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKSB8PiB3cml0ZV9jc3YoImNsZWFuZXJfbWRfZG9ub3JfZGVtb3MuY3N2IikKYGBgCgoKY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgfD4gd3JpdGVfY3N2KCJjbGVhbmVyX29vc19kb25vcl9kZW1vcy5jc3YiKQoKCgpJdCBsb29rcyBsaWtlIGluIHRoaXMgZGF0YSwgdGhlIHRvcCBjb250cmlidXRpbmcgemlwIGNvZGVzIGFyZSB0aGUgc2FtZSBmb3Igb3V0LW9mLXN0YXRlIGFuZCBpbi1zdGF0ZSBkb25hdGlvbnMuIFRoZSB0b3Agb3V0LW9mLXN0YXRlIGRvbm9ycyBkb25hdGVkIG11Y2ggbW9yZSB0aGFuIHRoZSBpbi1zdGF0ZSBkb25vcnMsIGFuZCB0aGVyZSB3ZXJlIG1vcmUgb2YgdGhlbSBpbiB0aGUgdG9wIHppcCBjb2Rlcy4gQSB0b3AgaW4tc3RhdGUgZG9ub3IgemlwIGNvZGUgaXMgQW5hcG9saXMsIGFuZCBkb2Vzbid0IGFwcGVhciBpbiB0aGUgdG9wIHRlbiB6aXAgY29kZXMgZm9yIG91dC1vZi1zdGF0ZS4KCkFzIHdlIGtlZXAgZ29pbmcgdG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24sIHdlIHNob3VsZCBjYWxjdWxhdGUgdGhlIGFtb3VudCBkb25hdGVkIHBlciBwZXJzb24uIFdlIHNob3VsZCBjb25zaWRlciBwcmVzZW50aW5nIHRoaXMgZGF0YSB3aXRoIHR3byBtYXBzIHNpZGUtYnktc2lkZS4gCgoKIyBRdWVzdGlvbiA0OiBBbW9uZyB0b3AgTWFyeWxhbmQgZG9ub3JzLCB3aGF0IHByb2Zlc3Npb25zIGRvbmF0ZSB0aGUgbW9zdCBtb25leSB0byBzZW5hdGUgY2FtcGFpZ25zPyAKCmBgYHtyfQppbmRpdmlkdWFsX2Rvbm9ycyAgPC0gZmluYWxfZGF0YV9zdGF0ZXN8Pgpncm91cF9ieShjb250cmlidXRvcl9uYW1lLCBjb250cmlidXRvcl96aXAsIGNvbnRyaWJ1dG9yX29jY3VwYXRpb24sIGNvbnRyaWJ1dG9yX2VtcGxveWVyKSB8PiAKICBzdW1tYXJpemUoCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQpIAogICkgfD4KICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpICAKCmpvYnNfdG9fY2xlYW4gPC0gaW5kaXZpZHVhbF9kb25vcnMgfD4gCiAgZ3JvdXBfYnkoY29udHJpYnV0b3Jfb2NjdXBhdGlvbikgfD4KICBzdW1tYXJpemUoCiAgICBudW1iZXJfam9icyA9IG4oKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAKICAgICB0b3RhbF9kb25hdGlvbnMgPSBzdW0odG90YWxfZG9uYXRlZCkKICApIHw+IGFycmFuZ2UoZGVzYyhudW1iZXJfam9icykpIHw+CndyaXRlX2Nzdigiam9ic190b19jbGVhbi5jc3YiKQoKYGBgCgpgYGB7cn0KYm9zc190b19jbGVhbiAgPC0gaW5kaXZpZHVhbF9kb25vcnMgfD4gCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfZW1wbG95ZXIpIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0ZWQpCiAgKSB8PiBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKSB8Pgp3cml0ZV9jc3YoImJvc3NfdG9fY2xlYW4uY3N2IikKYGBgCgoKYGBge3J9CmNsZWFuX2VtcGxveWVyIDwtIHJlYWRfY3N2KCJjbGVhbmVkX2Jvc3MuY3N2IikKY2xlYW5fb2NjdXBhdGlvbiA8LSByZWFkX2NzdigiY2xlYW5fam9icy5jc3YiKQoKY2xlYW5fb2NjdXBhdGlvbiB8PiAKICBncm91cF9ieShjbGVhbmVkX2pqb2JzKSAgfD4gCiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGlvbnMpKSB8PiAKICBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKQoKYGBgCmBgYHtyfQpjbGVhbl9vY2N1cGF0aW9uIHw+IAogIGdyb3VwX2J5KGNsZWFuZWRfampvYnMpICB8PiAKICBzdW1tYXJpemUoCiAgICBudW1iZXJfam9icyA9IG4oKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAKICAgICB0b3RhbF9kb25hdGVkID0gc3VtKHRvdGFsX2RvbmF0aW9ucykpIHw+IAogIGFycmFuZ2UoZGVzYyh0b3RhbF9kb25hdGVkKSkKCmBgYAoKCmBgYHtyfQpjbGVhbl9lbXBsb3llciB8PiAKICBncm91cF9ieShjbGVhbmVkX2Jvc3MpIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGlvbnMpCiAgKSB8PgogIGFycmFuZ2UoZGVzYyhudW1iZXJfam9icykpCmBgYAoKClRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCBJIHB1dCBhIGNzdiBvZiBvY2N1cGF0aW9ucyBpbnRvIE9wZW5SZWZpbmUuIFdlIG9yaWdpbmFsbHkgcGxhbm5lZCB0byBsaW1pdCB0aGUgZGF0YSBzZXQsIGJ1dCBJIGZvdW5kIHRoYXQgdGhlcmUgd2VyZSBvbmx5IDEsOTYzIGpvYiB0aXRsZXMgaW4gdGhlIGRhdGEgc2V0LCB3aGljaCBzZWVtZWQgbGlrZSBhIHJlYXNvbmFibGUgbnVtYmVyIHRvIHJlZmluZSBkb3duIGludG8gYSBzbWFsbGVyIGxpc3Qgb2Ygam9icy4gCgpUbyBkbyB0aGlzLCBJIGdyb3VwZWQgY2VydGFpbiBqb2JzIGludG8gY2F0ZWdvcmllcyBsaWtlICJkaXJlY3RvciIgYW5kICJleGVjdXRpdmUiIC0tIHNvIGpvYiB0aXRsZXMgbGlrZSAic2FsZXMgZGlyZWN0b3IiIHdlbnQgaW50byB0aGUgImRpcmVjdG9yIiBjYXRlZ29yeS4gCgpJIHRoaW5rIHRoZSBPcGVuUmVmaW5lIG1ldGhvZCBtYXkgYmUgZmxhd2VkL25vdCB0ZWxsIHVzIHZlcnkgbXVjaCBiZWNhdXNlIEkgd2FzIG9ubHkgYWJsZSB0byBnZXQgdGhlIGxpc3QgZG93biB0byAxLDQ2NCBqb2JzIGFmdGVyIGFib3V0IDEgaG91ciBvZiByZWZpbmluZy4gSSBhbHNvIHdvcnJ5IHRoYXQgdGhlIGNhdGVnb3JpemluZyBtZXRob2QgSSB1c2VkIG9ic3VyZXMgaW5mb3JtYXRpb24gdGhhdCBtaWdodCBiZSBpbXBvcnRhbnQgLS0gRGlyZWN0b3Igb2YgU2FsZXMgaXMgZGlmZmVyZW50IGZyb20gRGlyZWN0b3Igb2YgRWR1Y2F0aW9uLCBmb3IgZXhhbXBsZSwgYW5kIHRoZXNlIGpvYnMgd2VyZSBncm91cGVkIGludG8gdGhlIHNhbWUgcG9zaXRpb24uIEFuZCB0aGVyZSBhcmUgc3VjaCB2YXJpYXRpb25zIGluIGpvYiB0aXRsZSB0aGF0IEkgd2FzIG5vdCBhYmxlIHRvIGNhdGVnb3JpemUgYWxsIGpvYiB0aXRsZXMgd2VsbC4gCgpXaGF0IHdlIGNhbiB0ZWxsIGZyb20gdGhpcyBkYXRhIGlzIHRoYXQgdGhlIG1vc3QgZnJlcXVlbnRseS1oZWxkIGpvYnMgYW1vbmcgTWFyeWxhbmQgZG9ub3JzIGFyZSBsZWFkZXJzaGlwL21hbmFnZW1lbnQgcG9zaXRpb25zLCBzbyBsaWtlbHkgd2VsbC1wYWlkLiBUaGUgbW9zdCBtb25leSB3YXMgZG9uYXRlZCBieSBwZW9wbGUgd2hvIGFyZSBub3QgZW1wbG95ZWQgb3IgcmV0aXJlZC4gCgpXZSBzaG91bGQgY29uc2lkZXIgcmVwZWF0aW5nIHRoaXMgcXVlc3Rpb24gd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBlbXBsb3llcnMuIEkndmUgc3RhcnRlZCB0byBkbyB0aGlzIGluIE9wZW5SZWZpbmUsIGJ1dCB0aGlzIHdpbGwgdGFrZSBsb25nZXIsIGJlY2F1c2UgdGhlcmUgYXJlIG1vcmUgdGhhbiA3LDAwMCBkaWZmZXJlbnQgZW1wbG95ZXJzLiBIb3dldmVyLCBtYW55IG9mIHRoZXNlIHNlZW0gdG8gYmUgYWJsZSB0byBiZSByZWNvbmNpbGVkIGluIE9wZW5SZWZpbmUuIEFuZCBJJ20gaW50ZXJlc3RlZCB0byBzZWUgaG93IG1hbnkgZG9uYXRpb25zL2hvdyBtdWNoIG1vbmV5IHdhcyBkb25hdGVkIGJ5IHBlb3BsZSB3aG8gd29yayBmb3IgdG9wIGVtcGxveWVycyBpbiBNYXJ5bGFuZCwgbGlrZSBKb2hucyBIb3BraW5zLiAKCgojUXVlc3Rpb24gNTogV2hhdOKAmXMgdGhlIG1ha2V1cCBvZiBkb25hdGlvbnMgcmVjZWl2ZWQgYnkgSG9nYW4gYW5kIEFsc29icm9va3M/IFdoYXQgcGVyY2VudGFnZSBvZiB0aGVpciBvdmVyYWxsIGRvbmF0aW9ucyB3ZXJlIGxhcmdlIGFtb3VudHMgb2YgbW9uZXkgKHRvIGJlIGRlZmluZWQsIGJ1dCA+ICQxMDAwLCBmb3IgZXhhbXBsZSkgdnMgc21hbGwgYW1vdW50cz8KCmBgYHtyfQpob2dhbl9maWx0ZXJlZF9kYXRhIDwtIGZpbmFsX2RhdGEgfD4KICBmaWx0ZXIoY29tbWl0dGVlX25hbWUgJWluJSBjKCJIT0dBTiBGT1IgTUFSWUxBTkQgSU5DLiIpKQpsYXJnZV9kb25hdGlvbl90aHJlc2hvbGQgPC0gMTAwMAoKaG9nYW5fZmlsdGVyZWRfZGF0YSB8PiBtdXRhdGUoIGRvbmF0aW9uX2NhdGVnb3J5ID0gaWZlbHNlKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCA+IGxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCwgIkxhcmdlIiwgIlNtYWxsIikgKQoKaG9nYW5fY2F0ZWdvcnlfdG90YWxzIDwtIGhvZ2FuX2ZpbHRlcmVkX2RhdGEgfD4KICBtdXRhdGUoZG9uYXRpb25fY2F0ZWdvcnkgPSBpZmVsc2UoY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50ID4gbGFyZ2VfZG9uYXRpb25fdGhyZXNob2xkLCAiTGFyZ2UiLCAiU21hbGwiKSkgfD4KICBncm91cF9ieShkb25hdGlvbl9jYXRlZ29yeSkgfD4KICBzdW1tYXJpc2UodG90YWxfYW1vdW50ID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCmhvZ2FuX2NhdGVnb3J5X3RvdGFscyAlPiUgbXV0YXRlKCBwZXJjZW50YWdlID0gdG90YWxfYW1vdW50IC8gc3VtKHRvdGFsX2Ftb3VudCkgKiAxMDAgKQoKaG9nYW5fY2F0ZWdvcnlfdG90YWxzCmBgYAoKYGBge3J9CmFsc29icm9va3NfZmlsdGVyZWRfZGF0YSA8LSBmaW5hbF9kYXRhIHw+CiAgZmlsdGVyKGNvbW1pdHRlZV9uYW1lICVpbiUgYygiQUxTT0JST09LUyBGT1IgU0VOQVRFIikpCgpsYXJnZV9kb25hdGlvbl90aHJlc2hvbGQgPC0gMTAwMAoKYWxzb2Jyb29rc19jYXRlZ29yeV90b3RhbHMgPC0gYWxzb2Jyb29rc19maWx0ZXJlZF9kYXRhIHw+CiAgbXV0YXRlKGRvbmF0aW9uX2NhdGVnb3J5ID0gaWZlbHNlKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCA+IGxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCwgIkxhcmdlIiwgIlNtYWxsIikpIHw+CiAgZ3JvdXBfYnkoZG9uYXRpb25fY2F0ZWdvcnkpIHw+CiAgc3VtbWFyaXNlKHRvdGFsX2Ftb3VudCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgphbHNvYnJvb2tzX2NhdGVnb3J5X3RvdGFscyAgJT4lIG11dGF0ZSggcGVyY2VudGFnZSA9IHRvdGFsX2Ftb3VudCAvIHN1bSh0b3RhbF9hbW91bnQpICogMTAwICkKCmFsc29icm9va3NfY2F0ZWdvcnlfdG90YWxzCmBgYApBNTogSGVyZSB3ZSBzZWUgdGhhdCBIb2dhbiByZWNlaXZlcyBzaWduZmljYW50bHkgbW9yZSBtb25leSBpbiBnZW5lcmFsIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gQWRkaXRpb25hbGx5LCBIb2dhbiByZWNlaXZlcyBtYW55IG1vcmUgbGFyZ2UgZG9uYXRpb25zIChpbiBleGNlc3Mgb2YgbWlsbGlvbnMpIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gV2hlcmVhcywgdGhlIHNtYWxsIGRvbmF0aW9ucyBhcmUgYXJvdW5kIDYwMCwwMDAgbW9yZS4gVGhpcyBzaG93cyB0aGF0IGVpdGhlIEhvZ2FuIGhhcyBhIGxhcmdlciAiZmFuIGJhc2UiIG9mIHBlb3BsZSB3aG8gZG9uYXRlIHRvIGhpbSBvciBwZXJoYXBzIGhpcyBlbGVjdG9yYXRlIGlzIGp1c3Qgd2VhbHRoaWVyLiBBZGRpdGlvbmFsbHksaXQgd291bGQgYmUgaW50ZXJlc3RpbmcgdG8gbm90ZSB3aGV0aGVyIEhvZ2FuIGhhcyBhIGhpZ2hlciBhbW91bnQgb2YgZG9uYXRpb25zIGJlY2F1c2UgaGUgd2FzIGtub3duIGJlZm9yZS4gCg==